home *** CD-ROM | disk | FTP | other *** search
/ Chip: Internet / Chip Internet.iso / viewer / ghost / ps2ascii.ps < prev    next >
Text File  |  1993-05-29  |  13KB  |  392 lines

  1. %    Copyright (C) 1991, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2. %
  3. % This file is part of Ghostscript.
  4. %
  5. % Ghostscript is distributed in the hope that it will be useful, but
  6. % WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. % to anyone for the consequences of using it or for whether it serves any
  8. % particular purpose or works at all, unless he says so in writing.  Refer
  9. % to the Ghostscript General Public License for full details.
  10. %
  11. % Everyone is granted permission to copy, modify and redistribute
  12. % Ghostscript, but only under the conditions described in the Ghostscript
  13. % General Public License.  A copy of this license is supposed to have been
  14. % given to you along with Ghostscript so you can know your rights and
  15. % responsibilities.  It should be in a file named COPYING.  Among other
  16. % things, the copyright notice and this notice must be preserved on all
  17. % copies.
  18.  
  19. % Extract the ASCII text from a PostScript file.  Nothing is displayed.
  20. % Instead, ASCII information is written to stdout.  If SIMPLE is defined,
  21. % just the text is written, with a guess at line breaks and word spacing.
  22. % If SIMPLE is not defined, lines are written to stdout as follows:
  23. %
  24. %    F <height> <width> (<fontname>)
  25. %        indicate font height and width of a space
  26. %
  27. %    S <x> <y> (<string>) <width>
  28. %        display a string
  29. %
  30. %    P
  31. %        end of page
  32. % <height> is an integer expressed in tenths of a point
  33. % <width> is an integer in tenths of a point.
  34. % <x> and <y> are integer coordinates, in tenths of a point, with origin
  35. %   at lower left.
  36. % <string> and <fontname> are strings represented with the standard
  37. %   PostScript escape conventions.
  38. % The idea is similar to Glenn Reid's `distillery', only a lot more
  39. % simple-minded, and less robust.
  40.  
  41. % Note that this code will only work in all cases if systemdict is writable
  42. % and if `binding' the definitions of operators defined as procedures
  43. % is deferred.  For this reason, it is normally invoked with
  44. %    gs -q -dNODISPLAY -dNOBIND -dWRITESYSTEMDICT ps2ascii.ps
  45.  
  46. % Thanks to J Greely <jgreely@cis.ohio-state.edu> for improvements
  47. % to this code.
  48.  
  49. /QUIET true def
  50. systemdict wcheck { systemdict } { userdict } ifelse begin
  51. /SIMPLE dup where { pop true } { false } ifelse def
  52.  
  53. % Disable the display operators.
  54.  
  55. /eofill { newpath } odef
  56. /erasepage { } odef
  57. /fill { newpath } odef
  58. /stroke { newpath } odef
  59.  
  60. % The image operators must read the input, but do nothing.
  61.  
  62. /colorimage { gsave nulldevice //colorimage grestore } odef
  63. /image { gsave nulldevice //image grestore } odef
  64. /imagemask { gsave nulldevice //imagemask grestore } odef
  65.  
  66. % Redefine the end-of-page operators.
  67.  
  68. /copypage { SIMPLE { (\014) } { (P\n) } ifelse //print } odef
  69. /showpage { copypage erasepage initgraphics } odef
  70.  
  71. % Redefine `show'.
  72.  
  73. % Set things up so our output will be in tenths of a point, with origin at
  74. % lower left.  This isolates us from the peculiarities of individual devices.
  75.  
  76. /.show.ident.matrix matrix def
  77. /.show.ident
  78. % { //.show.ident.matrix defaultmatrix
  79. %        % Assume the original transformation is well-behaved.
  80. %   0.1 0 2 index dtransform abs exch abs max /.show.scale exch def
  81. %   0.1 dup 3 -1 roll scale
  82.  { gsave initmatrix
  83.         % Assume the original transformation is well-behaved.
  84.    0.1 0 dtransform abs exch abs max /.show.scale exch def
  85.    0.1 dup scale .show.ident.matrix currentmatrix
  86.    grestore
  87.  } bind def
  88. /.coord
  89.  { transform .show.ident itransform
  90.    exch round cvi exch round cvi
  91.  } odef
  92. /.dcoord
  93.  {        % Transforming distances is trickier, because
  94.         % the coordinate system might be rotated.
  95.    .show.ident pop
  96.    exch 0 dtransform
  97. %     dup 0 ne { dup mul exch dup mul add sqrt } { pop abs } ifelse
  98. dup mul exch dup mul add sqrt
  99.      .show.scale div round cvi
  100.    exch 0 exch dtransform
  101. %     exch dup 0 ne { dup mul exch dup mul add sqrt } { pop abs } ifelse
  102. dup mul exch dup mul add sqrt
  103.      .show.scale div round cvi
  104.  } odef
  105.  
  106. % Define a way to store and retrieve integers that survives save/restore.
  107. /.i.string (                ) def
  108. /.iget { cvi } bind def
  109. /.iput { exch //.i.string exch copy cvs pop } bind def
  110. /.inew { //.i.string length string dup 3 -1 roll .iput } bind def
  111. /.show.x 0 .inew def
  112. /.show.y 0 .inew def
  113. /.show.height 1000 .inew def
  114. % Remember the last character of the previous string; if it was a
  115. % hyphen preceded by a letter, we didn't output the hyphen.
  116. /.show.last (\000) def
  117.  
  118. % Make sure writing will work even if a program uses =string.
  119. /.show.string =string length string def
  120. /.show.=string =string length string def
  121. /.show==only
  122.  { //=string //.show.=string copy pop
  123.    dup type /stringtype eq
  124.     { dup length //.show.string length le
  125.        { dup rcheck { //.show.string copy } if
  126.        } if
  127.     } if
  128.    //.stdout exch write==only
  129.    //.show.=string //=string copy pop
  130.  } odef
  131.  
  132. /.showfont
  133. %(following comments are from J Greely)
  134. %old code - This didn't work right for me with all fonts.
  135. %
  136. % { 0 currentfont /FontBBox get dup 3 get exch 1 get sub
  137. %   currentfont /FontMatrix get dtransform dtransform
  138. %   exch abs exch abs max round
  139. %   (F ) //print //.stdout exch write==only (\n) //print
  140. % } odef
  141. %
  142. %unfortunately, my way bombs on one of my test files in
  143. %--%show_continue--(?!).  It's from dvi2ps, which molests
  144. %the fonts in some way. --jgreely
  145.  { gsave
  146.     % If we can't get the height and width of the font from
  147.     % the FontBBox, we just measure some characters.
  148.      currentfont /FontBBox .knownget not { {0 0 0 0} } if
  149.      aload pop exch 4 -1 roll sub 3 1 roll exch sub
  150.      2 copy max 0 ne
  151.       { currentfont /FontMatrix get dtransform
  152.       }
  153.       {    % Unfortunately, charpath is broken in some versions,
  154.     % so we use stringwidth and fudge.
  155.     (X) stringwidth pop dup 1.3 mul
  156.       }
  157.      ifelse .dcoord exch
  158.      currentfont /FontName .knownget not { () } if
  159.      dup type /nametype eq { //.show.string cvs } if
  160.    grestore
  161.     % Stack: height width fontname
  162.    SIMPLE
  163.     { pop pop //.show.height exch .iput }
  164.     { (F ) //print 3
  165.        { 2 index .show==only ( ) //print 3 -1 roll } repeat
  166.       pop pop pop (\n) //print
  167.     }
  168.    ifelse
  169.  } odef
  170.  
  171. % Define the letters -- characters which, if they occur followed by a hyphen
  172. % at the end of a line, cause the hyphen and line break to be ignored.
  173. /.letter.chars 100 dict def
  174. mark
  175.   65 1 90 { dup 32 add } for
  176. counttomark { StandardEncoding exch get .letter.chars exch dup put } repeat
  177. pop
  178.  
  179. % Define a set of characters which, if they occur at the start of a line,
  180. % are taken as indicating a paragraph break.
  181. /.break.chars 50 dict def
  182. mark
  183.   /bullet /dagger /daggerdbl /periodcentered /section
  184. counttomark { .break.chars exch dup put } repeat
  185. pop
  186.  
  187. % Define character translation to ASCII.
  188. % We have to do this for the entire character set.
  189. /.char.map 500 dict def
  190. /.chars.def { counttomark 2 idiv { .char.map 3 1 roll put } repeat pop } def
  191.     % Encode the printable ASCII characters.
  192. mark 32 1 126
  193.  { 1 string dup 0 4 -1 roll put
  194.    dup 0 get StandardEncoding exch get exch
  195.  }
  196. for .chars.def
  197.     % Encode accents.
  198. mark
  199.   /acute (') /caron (^) /cedilla (,) /circumflex (^)
  200.   /dieresis (") /grave (`) /ring (*) /tilde (~)
  201. .chars.def
  202.     % Encode the ISO accented characters.
  203. mark 192 1 255
  204.  { ISOLatin1Encoding exch get =string cvs
  205.    dup 0 1 getinterval 1 index dup length 1 sub 1 exch getinterval
  206.    .char.map 2 index known .char.map 2 index known and
  207.     { .char.map 3 -1 roll get .char.map 3 -1 roll get concatstrings
  208.       .char.map 3 1 roll put
  209.     }
  210.     { pop pop pop
  211.     }
  212.    ifelse
  213.  }
  214. for .chars.def
  215.     % Encode the remaining standard and ISO alphabetic characters.
  216. mark
  217.   /AE (AE) /Eth (DH) /OE (OE) /Thorn (Th)
  218.   /ae (ae) /eth (dh)
  219.   /ffi (ffi) /ffl (ffl) /fi (fi) /fl (fl)
  220.   /germandbls (ss) /oe (oe) /thorn (th)
  221. .chars.def
  222.     % Encode the other standard and ISO characters.
  223. mark
  224.   /brokenbar (|) /bullet (*) /copyright ((C)) /currency (#)
  225.   /dagger (#) /daggerdbl (##) /degree (o) /divide (/) /dotaccent (.)
  226.   /dotlessi (i)
  227.   /ellipsis (...) /emdash (--) /endash (-) /exclamdown (!)
  228.   /florin (f) /fraction (/)
  229.   /guillemotleft (<<) /guillemotright (>>)
  230.   /guilsingleft (<) /guilsingright (>) /hungarumlaut ("") /logicalnot (~)
  231.   /macron (_) /minus (-) /mu (u) /multiply (*)
  232.   /ogonek (,) /onehalf (1/2) /onequarter (1/4) /onesuperior (1)
  233.   /ordfeminine (-a) /ordmasculine (-o)
  234.   /paragraph (||) /periodcentered (*) /perthousand (o/oo) /plusminus (+-)
  235.   /questiondown (?) /quotedblbase (") /quotedblleft (") /quotedblright (")
  236.   /quotesinglbase (,) /quotesingle (') /registered ((R))
  237.   /section ($) /sterling (#)
  238.   /threequarters (3/4) /threesuperior (3) /trademark ((TM)) /twosuperior (2)
  239.   /yen (Y)
  240. .chars.def
  241.     % Encode a few common Symbol characters.
  242. mark
  243.   /asteriskmath (*) /copyrightsans ((C)) /copyrightserif ((C))
  244.   /greaterequal (>=) /lessequal (<=) /registersans ((R)) /registerserif ((R))
  245.   /trademarksans ((TM)) /trademarkserif ((TM))
  246. .chars.def
  247.  
  248. % Write out a string.  If it ends in a letter and a hyphen,
  249. % don't write the hyphen, and set .show.last to a hyphen;
  250. % otherwise, set .show.last to the character (or \000 if it was a hyphen).
  251. /.show.write    % <string>
  252.  { dup length 1 ge
  253.     { dup dup length 1 sub get
  254.       dup 45 eq        % hyphen
  255.        { 1 index length 1 gt
  256.           { 1 index dup length 2 sub get }
  257.       { //.show.last 0 get }
  258.      ifelse
  259.      currentfont /Encoding get exch get
  260.      //.letter.chars exch known
  261.       {    % Remove the hyphen
  262.         exch dup length 1 sub 0 exch getinterval exch
  263.       }
  264.       { pop 0
  265.       }
  266.      ifelse
  267.        }
  268.       if
  269.       //.show.last 0 3 -1 roll put
  270.     }
  271.    if
  272.     { dup currentfont /Encoding get exch get
  273.       dup //.char.map exch .knownget
  274.        { //.stdout exch writestring pop pop
  275.        }
  276.        { currentfont /Encoding dup StandardEncoding eq
  277.      exch ISOLatin1Encoding eq or
  278.       {    % Untranslated character in standard encoding
  279.         pop //.stdout exch write
  280.       }
  281.       {    % Character in non-standard encoding, substitute
  282.         pop pop //.stdout (*) writestring
  283.       }
  284.      ifelse
  285.        }
  286.       ifelse
  287.     }
  288.    forall
  289.  } odef
  290. /.showstring
  291.  { currentpoint .coord
  292.    3 -1 roll dup stringwidth 1 index 0 rmoveto
  293.    .dcoord pop
  294.     % Stack: x y string width
  295.    SIMPLE
  296.     { 2 index //.show.y .iget ne
  297.        {    % Try to figure out whether we have a line break
  298.         % or a paragraph break.
  299.      2 index //.show.y .iget sub abs
  300.      //.show.height .iget 1.3 mul ge
  301.      2 index length 0 gt
  302.       { 2 index 0 get currentfont /Encoding get exch get
  303.         //.break.chars exch known { pop true } if
  304.       }
  305.      if
  306.       { (\n\n)    % Paragraph
  307.       }
  308.       { ( )        % Line
  309.       }
  310.      ifelse //print
  311.      //.show.y 3 index .iput
  312.          //.show.x 4 index .iput
  313.        }
  314.        {    % If the word processor split a hyphenated word within
  315.         % the same line, put out the hyphen now.
  316.      //.show.last 0 get 45 eq { (-) //print } if
  317.        }
  318.       ifelse
  319.       3 index //.show.x .iget 10 add gt
  320.        { ( ) //print
  321.        }
  322.       if
  323.       4 1 roll .show.write pop add //.show.x exch .iput
  324.     }
  325.     { (S ) //print
  326.       4 -1 roll .show==only ( ) //print
  327.       3 -1 roll .show==only ( ) //print
  328.       exch .show==only ( ) //print
  329.       .show==only (\n) //print
  330.     }
  331.    ifelse
  332.  } odef
  333.      
  334. /show
  335.  { .showfont .showstring
  336.  } odef
  337.  
  338. % Redefine the other string display operators in terms of `show'.
  339.  
  340. /.show1.string ( ) def
  341. /.show1 { //.show1.string exch 0 exch put //.show1.string .showstring } odef
  342. /ashow
  343.  { .showfont
  344.    { .show1 2 copy rmoveto } forall
  345.    pop pop
  346.  } odef
  347. /awidthshow
  348.  { .showfont
  349.     { dup .show1 4 index eq { 4 index 4 index rmoveto } if
  350.       2 copy rmoveto
  351.     }
  352.    forall
  353.    pop pop pop pop pop
  354.  } odef
  355. /widthshow
  356.  { .showfont
  357.    //.show1.string 0 4 -1 roll put
  358.     { //.show1.string search not { exit } if
  359.       .showstring .showstring
  360.       2 index 2 index rmoveto
  361.     } loop
  362.    .showstring pop pop
  363.  } odef
  364. /kshow
  365.  { .showfont
  366.    { .show1 dup exec } forall pop
  367.  } odef
  368.  
  369. % Redirect the printing operators.
  370.  
  371. /.stdout (_temp_.out) (w) file def
  372. /.stderr (_temp_.err) (w) file def
  373. /print { //.stdout exch writestring } odef
  374.  
  375. end
  376.  
  377. % Bind the operators we just defined, and all the others if we didn't
  378. % do it before.  Also reenable 'bind' for future files.
  379.  
  380. .bindoperators
  381. NOBIND currentdict systemdict ne and
  382.  { systemdict begin .bindoperators end }
  383. if
  384. NOBIND
  385.  { /bind /.bind load def }
  386. if
  387.  
  388. % Make systemdict read-only if it wasn't already.
  389.  
  390. systemdict wcheck { systemdict readonly pop } if
  391.